package nl.gamayun.whohasit;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.database.Cursor;
import android.util.Log;

public class WhoHasItHandlerImpl implements WhoHasItHandler
{
	static final private String	TAG	= WhoHasItHandler.class.getSimpleName();
	private Map<Long,Loan> loans = new HashMap<Long, Loan>();
	private List<Loan> filteredLoans = new ArrayList<Loan>();
	private WhoHasItDBAdapter dbAdapter;
	private LoanAdapter loanAdapter;
	private Cursor loansCursor;
	
	static final Comparator<Loan>	ON_DATE_ASC = new Comparator<Loan>()
		{
			public int compare(Loan e1, Loan e2)
			{
				return e1.getDate().compareTo(e2.getDate());
			}
		};	
	
		static final Comparator<Loan>	ON_DATE_DESC = new Comparator<Loan>()
		{
			public int compare(Loan e1, Loan e2)
			{
				return e2.getDate().compareTo(e1.getDate());
			}
		};	
	
		static final Comparator<Loan>	ON_LOANER_ASC = new Comparator<Loan>()
		{
			public int compare(Loan e1, Loan e2)
			{
				return e2.getLoanerName().compareTo(e1.getLoanerName());
			}
		};	
	
	public WhoHasItHandlerImpl(Context _context)
	{
		Log.d(TAG, "WhoHasItHandlerImpl");
		dbAdapter = new WhoHasItDBAdapter(_context);
		dbAdapter.open();
		/* Initieel vullen database voor test
		Loan loan = new Loan(new Date(), "A book", "A nice book", "Mr. Anderson", TYPE.lent_to );
		dbAdapter.insertLoan(loan);
		Loan loan = new Loan(new Date(), "header", "detail", "Mr. Anderson", TYPE.lent_to );
		dbAdapter.insertLoan(loan);
		loan = new Loan(new Date(), "header", "detail", "Mr. Anderson", TYPE.lent_from );;
		dbAdapter.insertLoan(loan);
		loan = new Loan(new Date(), "header", "detail", "Mr. Smith", TYPE.lent_from );;
		dbAdapter.insertLoan(loan);
		*/
		updateMap();
		dbAdapter.close();
		
		int resId = R.layout.loanlist_item;
		loanAdapter = new LoanAdapter(WhoHasIt.getContext(), resId, getAllLoans());
		
	}
	
	public int getNumberOfLoans()
	{
		Log.d(TAG, "getNumberOfLoans");
		return loans.size();
	}

	public int getNumberOfLoansForType(TYPE type)
	{
		Log.d(TAG, "getNumberOfLoansForType");
		return getLoans(null, type).size();
	}

	public Loan getNewestLoan()
	{
		Log.d(TAG, "getNewestLoan");
		List<Loan> sortedLoans = getLoans(null, null);
		if (sortedLoans.size() == 0)
			return null;
		
		Collections.sort(sortedLoans, ON_DATE_DESC);
		return sortedLoans.get(0);
	}

	public Loan getOldestLoan()
	{
		Log.d(TAG, "getOldestLoan");
		List<Loan> sortedLoans = getLoans(null, null);
		if (sortedLoans.size() == 0)
			return null;
		
		Collections.sort(sortedLoans, ON_DATE_ASC);
		return sortedLoans.get(0);
	}

	public String getLentMostFrom()
	{
		Log.d(TAG, "getLentMostFrom");
		List<Loan> sortedLoans = getLoans(null, TYPE.lent_from);
		Collections.sort(sortedLoans, ON_LOANER_ASC);
		return getMostLoaner(sortedLoans);
	}

	public String getLentMostTo()
	{
		Log.d(TAG, "getLentMostTo");
		List<Loan> sortedLoans = getLoans(null, TYPE.lent_to);
		Collections.sort(sortedLoans, ON_LOANER_ASC);
		return getMostLoaner(sortedLoans);
	}

	private String getMostLoaner(List<Loan> loans)
	{
		Log.d(TAG, "getMostLoaner");
		String mostLoaner = "";
		if (loans.size() == 0)
			return mostLoaner;

		mostLoaner = loans.get(0).getLoanerName();
		Integer most = 0;
		Integer counter = 0; 
		for (Loan loan: loans)
		{
			if (mostLoaner.equals(loan.getLoanerName()))
			{
				counter++;
			}
			else
			{
				if (most < counter)
				{
					most = counter;
					mostLoaner = loan.getLoanerName();
					counter = 0;
				}
			}
			if (most < counter)
			{
				most = counter;
				mostLoaner = loan.getLoanerName();
			}
		}
		return mostLoaner;
	}
	
	public Collection<Loan> getLoans()
	{
		Log.d(TAG, "getLoans()");
		return loans.values();
	}
	
	public List<Loan> getAllLoans()
	{
		Log.d(TAG, "getAllLoans()");
		List<Loan> sortedLoans = new ArrayList<Loan>(loans.values());
		Collections.sort(sortedLoans, ON_DATE_DESC);
		return sortedLoans;
	}

	public List<Loan> getAllLoansByType(TYPE type)
	{
		Log.d(TAG, "getAllLoansByType("+type.getTypeValue()+")");
		return getLoans(null, type);
	}

	public List<Loan> getAllLoansByLoaner(String loanerName)
	{
		Log.d(TAG, "getAllLoansByLoaner("+loanerName+")");
		return getLoans(loanerName, null);
	}

	public List<Loan> getAllLoansByLoaner(String loanerName, TYPE type)
	{
		Log.d(TAG, "getAllLoansByLoaner("+loanerName+","+type.getTypeValue()+")");
		return getLoans(loanerName, type);
	}

	public void addLoan(Loan loan)
	{
		Log.d(TAG, "addLoan("+loan+")");
		dbAdapter.open();
		long id = dbAdapter.insertLoan(loan);
		loan.setLoanID(id);
		dbAdapter.close();
		loans.put(loan.getLoanID(), loan);
		loanAdapter.add(loan);
		loanAdapter.notifyDataSetChanged();
	}

	public void updateLoan(Loan loan)
	{
		Log.d(TAG, "updateLoan("+loan+")");
		dbAdapter.open();
		dbAdapter.updateLoan(loan.getLoanID(), loan);
		dbAdapter.close();
		loans.put(loan.getLoanID(), loan);
		loanAdapter.notifyDataSetChanged();
	}

	public void removeLoan(Loan loan)
	{
		Log.d(TAG, "removeLoan("+loan+")");
		dbAdapter.open();
		dbAdapter.removeLoan(loan.getLoanID());
		dbAdapter.close();
		loans.remove(loan.getLoanID());
		loanAdapter.remove(loan);
		loanAdapter.notifyDataSetChanged();
	}

	private List<Loan> getLoans(String loanerName, TYPE type)
	{
		Log.d(TAG, "getLoans("+loanerName+","+type+")");
		filteredLoans.clear();
		boolean addToFiltered;
		for (Loan loan : loans.values()) {
			addToFiltered = true;
			if (loanerName != null && !loanerName.trim().equals("")
					&& addToFiltered) {
				addToFiltered = loanerName.equals(loan.getLoanerName());
			}
			if (type != null && addToFiltered) {
				addToFiltered = type.equals(loan.getType());
			}
			if (addToFiltered) {
				filteredLoans.add(loan);
			}

		}
		Collections.sort(filteredLoans, ON_DATE_DESC);
		
		return filteredLoans;
	}

	private synchronized void updateMap()
	{
		Log.d(TAG, "updateMap()");
		loansCursor = dbAdapter.getAllLoanItemsCursor();
		loansCursor.requery();
		loans.clear();
		if (loansCursor.moveToFirst())
			do
			{
				Loan loan = dbAdapter.getLoan(loansCursor.getLong(WhoHasItDBAdapter.LOAN_ID_COLUMN));
				loans.put(loan.getLoanID(), loan);
			}
			while (loansCursor.moveToNext());
		loansCursor.close();
	}
	
	public void onDestroy()
	{
		Log.d(TAG, "onDestroy()");
		// Close the database
		if (dbAdapter != null)
			dbAdapter.close();
	}

	/* (non-Javadoc)
	 * @see nl.gamayun.whohasit.WhoHasItHandler#getLoan(long)
	 */
	public Loan getLoan(long loanId) 
	{
		return loans.get(loanId);
	}

	public int getDatabaseVersion()
	{
		return dbAdapter.getDatabaseVersion();
	}

	@Override
	public LoanAdapter getLoanAdapter() 
	{
		return loanAdapter;
	}
	
	
}
